package com.example.algorithm.Singleton;

/**
 * 双检查锁
 * Created by ZMJ on 2020/1/10.
 */
public class DoubleCheckSingleton {

    private static volatile DoubleCheckSingleton singleton = null;

    private DoubleCheckSingleton() {}

    public DoubleCheckSingleton getInstance() {
        if (null == singleton) {
            synchronized (DoubleCheckSingleton.class) {
                if (null == singleton) {
                    singleton = new DoubleCheckSingleton();
                }
            }
        }
        return singleton;
    }

}

/*
从字节码可以看到创建一个对象实例，可以分为三步：
1,分配对象内存
2,调用构造器方法，执行初始化
3,将对象引用赋值给变量。
volatile 是为了防止指令重排序

volatile 作用
正确的双重检查锁定模式需要需要使用 volatile。volatile主要包含两个功能。
保证可见性。使用 volatile定义的变量，将会保证对所有线程的可见性。
禁止指令重排序优化。由于 volatile禁止对象创建时指令之间重排序，所以其他线程不会访问到一个未初始化的对象，从而保证安全性。
注意，volatile禁止指令重排序在 JDK 5 之后才被修复.

对象的创建可能发生指令的重排序，使用 volatile可以禁止指令的重排序，保证多线程环境内的系统安全。




 */
